package com.hcss.common.redis.config;

import com.alibaba.fastjson.support.spring.GenericFastJsonRedisSerializer;
import com.hcss.common.util.EmptyUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisNode;
import org.springframework.data.redis.connection.RedisSentinelConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import redis.clients.jedis.JedisPoolConfig;

import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @desc redis配置类
 * @author maxiaoming
 * @date 2018年6月19日 上午10:40:59
 * @company 浙江鸿程计算机系统有限公司 
 */
@Configuration
@EnableCaching
@Slf4j
public class RedisConfig extends CachingConfigurerSupport {

    @Value("${spring.redis.sentinel.master:}")
    private String master;

    @Value("${spring.redis.sentinel.nodes:}")
    private String nodes;

	/**
	 * redispool 配置信息
	 */
	@Bean
    @ConfigurationProperties(prefix = "spring.redis.pool")
	public JedisPoolConfig getRedisConfig() {
		return new JedisPoolConfig();
	}

    /**
     * redis 哨兵模式配置信息
     * @return
     */
    @Bean
    public RedisSentinelConfiguration getSentinelConfig(){
	    if (EmptyUtil.isHaveEmpty(master, nodes)) {
	        return null;
        }
        RedisSentinelConfiguration sentinelConfig = new RedisSentinelConfiguration();
        // master名称
        sentinelConfig.setMaster(master);
        // redis各节点
        Set<RedisNode> redisNodes = new HashSet<>();
        for (String node : nodes.split(",")) {
            redisNodes.add(new RedisNode(node.split(":")[0], Integer.parseInt(node.split(":")[1])));
        }
        sentinelConfig.setSentinels(redisNodes);
        return sentinelConfig;
    }

	/**
	 * connectionFactory
	 */
	@Bean(name = "jedisConnectionFactory")
	@ConfigurationProperties(prefix = "spring.redis")
	public JedisConnectionFactory getConnectionFactory() {
		JedisConnectionFactory factory = new JedisConnectionFactory(getSentinelConfig(), getRedisConfig());
		factory.setUsePool(true);
		return factory;
	}

	/**
	 * 操作模板类
	 */
	@Bean("redisTemplate")
	public <T> RedisTemplate<String, T> getRedisTemplate() {
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        GenericFastJsonRedisSerializer genericFastJsonRedisSerializer = new GenericFastJsonRedisSerializer();
        RedisTemplate<String, T> template = new RedisTemplate<String, T>();
        template.setKeySerializer(stringRedisSerializer);
        template.setHashKeySerializer(stringRedisSerializer);
        template.setValueSerializer(genericFastJsonRedisSerializer);
        template.setHashValueSerializer(genericFastJsonRedisSerializer);
        template.setDefaultSerializer(genericFastJsonRedisSerializer);
        template.setConnectionFactory(getConnectionFactory());
        template.afterPropertiesSet();
        return template;
	}

	/**
	 * 操作模板类
	 */
	@Bean("shiroRedisTemplate")
	public <T> RedisTemplate<String, T> getShiroRedisTemplate() {
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        GenericJackson2JsonRedisSerializer jackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
        RedisTemplate<String, T> template = new RedisTemplate<String, T>();
        template.setKeySerializer(stringRedisSerializer);
        template.setHashKeySerializer(stringRedisSerializer);
        template.setValueSerializer(jackson2JsonRedisSerializer);
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.setDefaultSerializer(jackson2JsonRedisSerializer);
        template.setConnectionFactory(getConnectionFactory());
        template.afterPropertiesSet();
        return template;
	}

	@Bean
    public CacheManager cacheManager(RedisTemplate shiroRedisTemplate) {
        return new RedisCacheManager(shiroRedisTemplate);
    }

    /**
     * 主键生成器
     *
     * @return
     */
    @Bean
    public KeyGenerator commonKeyGenerator() {
        return new KeyGenerator() {
            @Override
            public Object generate(Object target, Method method, Object... params) {
                StringBuilder sb = new StringBuilder();
                sb.append(target.getClass().getName());
                sb.append(method.getName());
                for (Object obj : params) {
                    sb.append(obj.toString());
                }
                return sb.toString();
            }
        };

    }
}
